import java.util.ArrayList;
import java.util.List;

// 自定义异常类：工作时长异常
class InvalidWorkHoursException extends Exception {
    public InvalidWorkHoursException(String message) {
        super(message);
    }
}

// 员工基类
abstract class Employee {
    private String name;    // 姓名       
    private String empId;   // 工号

    public Employee(String name, String empId) {
        this.name = name;
        this.empId = empId;
    }

    // 获取姓名
    public String getName() {
        return name;
    }

    // 获取工号
    public String getEmpId() {
        return empId;
    }

    // 抽象方法：计算薪资
    public abstract double calculateSalary() throws InvalidWorkHoursException;

    // 抽象方法：生成工资条
    public abstract String generatePaySlip();
}

// 普通员工子类
class RegularEmployee extends Employee {
    private double hourlyRate;  // 时薪
    private double workHours;   // 工作时长

    public RegularEmployee(String name, String empId, double hourlyRate, double workHours) {
        super(name, empId);
        this.hourlyRate = hourlyRate;
        this.workHours = workHours;
    }

    @Override
    public double calculateSalary() throws InvalidWorkHoursException {
        // 验证工作时长合法性
        if (workHours < 0 || workHours > 168) {  // 假设每周最大工作时长不超过168小时
            throw new InvalidWorkHoursException("工作时长异常：" + workHours + "小时（有效范围0-168）");
        }
        return hourlyRate * workHours;
    }

    @Override
    public String generatePaySlip() {
        try {
            StringBuilder sb = new StringBuilder();
            sb.append("===== 工资条 =====\n");
            sb.append("姓名：").append(getName()).append("\n");
            sb.append("工号：").append(getEmpId()).append("\n");
            sb.append("员工类型：普通员工\n");
            sb.append("时薪：").append(hourlyRate).append("元\n");
            sb.append("工作时长：").append(workHours).append("小时\n");
            sb.append("应发工资：").append(calculateSalary()).append("元\n");
            sb.append("==================");
            return sb.toString();
        } catch (InvalidWorkHoursException e) {
            return "工资计算错误：" + e.getMessage();
        }
    }
}

// 管理人员子类
class Manager extends Employee {
    private double monthlySalary;  // 月薪
    private double bonus;          // 奖金

    public Manager(String name, String empId, double monthlySalary, double bonus) {
        super(name, empId);
        this.monthlySalary = monthlySalary;
        this.bonus = bonus;
    }

    @Override
    public double calculateSalary() {
        // 管理人员薪资计算无特殊异常（假设月薪和奖金已预先验证）
        return monthlySalary + bonus;
    }

    @Override
    public String generatePaySlip() {
        StringBuilder sb = new StringBuilder();
        sb.append("===== 工资条 =====\n");
        sb.append("姓名：").append(getName()).append("\n");
        sb.append("工号：").append(getEmpId()).append("\n");
        sb.append("员工类型：管理人员\n");
        sb.append("月薪：").append(monthlySalary).append("元\n");
        sb.append("奖金：").append(bonus).append("元\n");
        sb.append("应发工资：").append(calculateSalary()).append("元\n");
        sb.append("==================");
        return sb.toString();
    }
}

// 员工薪资管理系统
public class SalaryManagementSystem {
    private List<Employee> employees;  // 存储所有员工

    public SalaryManagementSystem() {
        employees = new ArrayList<>();
    }

    // 添加员工
    public void addEmployee(Employee emp) {
        employees.add(emp);
    }

    // 显示所有员工工资条
    public void displayAllPaySlips() {
        for (Employee emp : employees) {
            System.out.println(emp.generatePaySlip());
            System.out.println();  // 空行分隔
        }
    }


    // 主方法测试
    public static void main(String[] args) {
        SalaryManagementSystem system = new SalaryManagementSystem();

        // 添加普通员工
        try {
            system.addEmployee(new RegularEmployee("张三", "EMP001", 50, 160));  // 正常时长
            system.addEmployee(new RegularEmployee("李四", "EMP002", 60, 180));  // 异常时长（超过168）
        } catch (Exception e) {
            System.out.println("添加员工失败：" + e.getMessage());
        }

        // 添加管理人员
        system.addEmployee(new Manager("王五", "MGR001", 20000, 5000));
        system.addEmployee(new Manager("赵六", "MGR002", 25000, 8000));

        // 显示所有工资条
        system.displayAllPaySlips();
    }
}